package e2e

import (
	"slices"
	"testing"

	"github.com/lab-online/pkg/auth"
	"github.com/lab-online/pkg/e2e"
	"github.com/lab-online/pkg/resp"
	"github.com/stretchr/testify/assert"
)

type importStudentReqDataItem struct {
	Name     string `json:"name"`
	Username string `json:"username"`
	Password string `json:"password"`
}

type importStudentRespDataItem struct {
	Name     string    `json:"name"`
	Username string    `json:"username"`
	Role     auth.Role `json:"role"`
}

type importStudentSuccessResp = resp.SuccessRespBody[[]importStudentRespDataItem]

func (ctx *context) defineImportStudentRequest(
	username string,
	role auth.Role,
	body []importStudentReqDataItem,
) *e2e.Request {
	return &e2e.Request{
		Method: "POST",
		Path:   ctx.Prefix + "/v1/users/import",
		Body:   body,
		Header: map[string]string{
			"Authorization": ctx.GenBearerToken(username, role),
		},
	}
}

func (ctx *context) CaseImportStudent() (string, func(*testing.T)) {
	filepath := e2e.ParseRelativeFilePath("testdata/import_student.json")
	testdata := e2e.ReadTestJSONFile[any](filepath)
	return e2e.DefineArgumentsValidateDescribe[any](ctx.Context, testdata)
}

func (ctx *context) CaseImportStudent1() (string, func(*testing.T)) {
	request := ctx.defineImportStudentRequest("teacher1", auth.RoleTeacher,
		[]importStudentReqDataItem{
			{"student1", "00240229", "12345678"},
			{"student2", "01240229", "12345678"},
			{"student2", "02240229", "12345678"},
			{"student2", "03240229", "12345678"},
			{"student2", "04240229", "12345678"},
			{"student2", "05240229", "12345678"},
			{"student2", "06240229", "12345678"},
			{"student2", "07240229", "12345678"},
			{"student2", "08240229", "12345678"},
			{"student2", "09240229", "12345678"},
			{"student2", "10240229", "12345678"},
			{"student2", "11240229", "12345678"},
			{"student2", "12240229", "12345678"},
			{"student2", "13240229", "12345678"},
			{"student2", "14240229", "12345678"},
			{"student2", "15240229", "12345678"},
			{"student2", "16240229", "12345678"},
			{"student2", "17240229", "12345678"},
			{"student2", "18240229", "12345678"},
			{"student2", "19240229", "12345678"},
		})
	return "批量导入学生", func(t *testing.T) {
		response := ctx.JSONRequest(request)

		assert.Equal(t, 201, response.Code)

		body := e2e.JSONBodyParser[importStudentSuccessResp](response)

		assert.Equal(t, 20105, body.Code)
		assert.Equal(t, 20, len(body.Data))

		assert.True(t, slices.ContainsFunc(body.Data, func(item importStudentRespDataItem) bool {
			return item.Username == "00240229" && item.Name == "student1" && item.Role == auth.RoleStudent
		}))
	}
}

func (ctx *context) CaseImportStudent2() (string, func(*testing.T)) {
	request := ctx.defineImportStudentRequest("teacher1", auth.RoleTeacher,
		[]importStudentReqDataItem{{"student2", "00240229", "12345678"}})
	return "导入学生,用户名已存在,仅添加student权限", func(t *testing.T) {
		response := ctx.JSONRequest(request)
		assert.Equal(t, 201, response.Code)

		body := e2e.JSONBodyParser[importStudentSuccessResp](response)

		assert.Equal(t, 20105, body.Code)
		assert.Equal(t, "student1", body.Data[0].Name)
		assert.Equal(t, "00240229", body.Data[0].Username)
		assert.Equal(t, auth.RoleStudent, body.Data[0].Role)
	}
}

func (ctx *context) CaseImportStudent3() (string, func(*testing.T)) {
	ctx.utilsCreateUser("04240302", auth.RoleTeacher, "12345678")
	ctx.utilsDeleteUser("04240302")

	request := ctx.defineImportStudentRequest("teacher1", auth.RoleTeacher,
		[]importStudentReqDataItem{{"student2", "04240302", "12345678"}})
	return "导入学生时,有用户名曾被软删除", func(t *testing.T) {
		response := ctx.JSONRequest(request)
		assert.Equal(t, 201, response.Code)

		body := e2e.JSONBodyParser[importStudentSuccessResp](response)

		assert.Equal(t, 20105, body.Code)
		assert.Equal(t, "student2", body.Data[0].Name)
		assert.Equal(t, "04240302", body.Data[0].Username)
		assert.Equal(t, auth.RoleStudent, body.Data[0].Role)
	}
}
